home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / program / amos / amoslist.lzh / AMOSLIST / 000239_amos-request@svcs1.digex.net_Mon Sep 18 16:53:25 1995.msg < prev    next >
Internet Message Format  |  1995-10-02  |  23KB

  1. Received: from svcs1.digex.net (svcs1.digex.net [204.91.197.224]) by mail1.access.digex.net (8.6.12/8.6.12) with ESMTP id QAA27344;  for <mcox@access.digex.net> ; Mon, 18 Sep 1995 16:53:24 -0400
  2. Received: (from daemon@localhost) by svcs1.digex.net (8.6.12/8.6.12) id OAA01210 for amos-out; Mon, 18 Sep 1995 14:09:43 -0400
  3. Received: from mail1.access.digex.net (mail1.access.digex.net [205.197.247.2]) by svcs1.digex.net (8.6.12/8.6.12) with ESMTP id OAA01203 for <amos-list@svcs1.digex.net>; Mon, 18 Sep 1995 14:09:37 -0400
  4. Received: from mail.mel.aone.net.au (mail.mel.aone.net.au [203.12.176.157]) by mail1.access.digex.net (8.6.12/8.6.12) with ESMTP id OAA04827;  for <amos-list@access.digex.net> ; Mon, 18 Sep 1995 14:09:33 -0400
  5. Received: from kyoko.mpx.com.au (kyoko.mpx.com.au [203.2.75.2]) by mail.mel.aone.net.au (8.6.11/8.6.11) with ESMTP id EAA09336 for <amos-list@access.digex.net>; Tue, 19 Sep 1995 04:09:30 +1000
  6. Received: from cristal.mpx.com.au by kyoko.mpx.com.au with smtp
  7.     (Smail3.1.29.1 #7) id m0sukf9-0006OKC; Tue, 19 Sep 95 04:11 EST
  8. Received: from comlink.mpx.com.au by cristal.mpx.com.au with uucp
  9.     (Smail3.1.28.1 #3) id m0sujuV-0000QgC; Tue, 19 Sep 95 03:23 EDT
  10. Received: by comlink.mpx.com.au (V1.16/Amiga)
  11.     id AA024zj; Mon, 18 Sep 95 21:21:08 1100
  12. Date: Mon, 18 Sep 95 21:21:08 1100
  13. Message-Id: <9509190321.AA024zi@comlink.mpx.com.au>
  14. From: Darryl_Lewis@comlink.mpx.com.au (Darryl Lewis)
  15. To: amos-list@access.digex.net
  16. Subject: Re: Amos Pro Sound Editor (Doom in AMOS)
  17. Status: RO
  18. X-Status: 
  19.  
  20. > PH> P.s. To all those who think they can write DOOM in AMOS - Maybe
  21. > PH> on chris hodges 68060, if he had 6 running in parallel! (P.s. AMOS 
  22. > PH> 3D's interpretation of the word texture mapping doesn't count - It 
  23. > PH> just draws smaller vector objects on the surface, and looks crap). 
  24.  
  25.  PH> You are right about that the 3d polygon mapping is slow, but that
  26.  PH> isn't 
  27.  PH> what Doom does. Wolfenstein & doom use raycasting method which is
  28.  PH> (usually) much faster than polygon based approach.
  29.  
  30. I still think your best bet is to look for that maze game that I got from
  31. aminet. I'll try and find it and tell every one the name. It uses bobs to
  32. draw the screen components. It needs some work, but the basics are there.
  33. Till 
  34. then...if you are really that interested in how doom works look at the tmap
  35. demo on aminet or read this:
  36.  
  37.  
  38. 1:  Definition of Terms
  39. ======================
  40.  
  41.      Throughout this document I will be making use of many graphical terms
  42. using my understanding of them as they apply to this algorithm. I will
  43. explain all the terms below. Feel free to skip this part....
  44.  
  45. Texture:
  46.      A texture for the purpose of this is a square image.
  47.  
  48. U and V:
  49.      U and V are the equivelants of x and y but are in texture space.
  50. ie They are the the two axies of the two dimensional texture.
  51.  
  52. Screen:
  53.      For my purposes 'screen' is the window we wish to fill: it doesn't
  54. have to be the whole screen.
  55.  
  56. Affine Mapping:
  57.      A affine mapping is a texture map where the texture is sampled
  58. in a linear fashion in both U and V.
  59.  
  60. Biquadratic Mapping:
  61.      A biquadratic mapping is a mapping where the texture is sampled
  62. along a curve in both U and V that approximates the perspective transform.
  63. This gives almost proper forshortening.
  64.  
  65.  
  66. Projective Mapping:
  67.      A projective mapping is a mapping where a changing homogenous
  68. coordinated is added to the texture coordinateds to give (U,V,W) and
  69. a division is performed at every pixel. This is the mathematically and
  70. visual correct for of texture mapping for the square to quadrilateral
  71. mappings we are using.
  72.      (As an aside it is possible to do a projective mapping without
  73. the divide (or 3 multiplies) but that is totally unrelated to the matter
  74. in hand...)
  75.  
  76. Ray Casting:
  77.      Ray Casting in this context is back-firing 'rays' along a two
  78. dinesional map. The rays do however follow heights... more on that later
  79.  
  80. Sprite:
  81.      A Sprite is a bitmap that is either a monster or an object. To
  82. put it another way it is anything that is not made out of wall or
  83. floor sectins.
  84.  
  85. Sprite Scaling:
  86.      By this I mean scaling a bitmap in either x or y or both.
  87.  
  88. Right... Now thats over with onto the foundation:
  89.  
  90. 2:   Two Dimensional Ray Casting Techniques
  91. ===========================================
  92.  
  93.      In order to make this accessible to anyone I will start by
  94. explaining 2d raycasting as used in Wolfenstein 3d style games.
  95.  
  96.   2.1: Wolfenstien 3D Style Techniques...
  97.   =======================================
  98.  
  99.        Wolfenstein 3d was a game that rocked the world (well me anyway!).
  100.   It used a technique where you fire a ray accross a 2d grid based map to
  101.   find all its walls and objects. The walls were then drawn vertically
  102.   using sprite scaling techniques to simulate texture mapping.
  103.  
  104.        The tracing accross the map looked something like this;
  105.  
  106.  
  107.      =============================================
  108.      =   =   =   =   =   =  /=   =   =   =   =   =
  109.      =   =   =   =   =   = / =   =   =   =   =   =
  110.      =   =   =   =   =   =/  =   =   =   =   =   =
  111.      ====================/========================
  112.      =   =   =   =   =  /=   =   =   =   =   =   =
  113.      =   =   =   =   = / =   =   =   =   =   =   =
  114.      =   =   =   =   =/  =   =   =   =   =   =   =
  115.      ================/============================
  116.      =   =   =   =  /#   =   =   =   =   =   =   =
  117.      =   =   =   = / #   =   =   =   =   =   =   =
  118.      =   =   =   =/  #   =   =   =   =   =   =   =
  119.      ============/===#########====================
  120.      =   =   =  /=   =   =   #   =   =   =   =   =
  121.      =   =   = / =   =   =   #   =   =   =   =   =
  122.      =   =   =/  =   =   =   #   =   =   =   =   =
  123.      ========/===============#====================
  124.      =   =  /=   =   =   =   #   =   =   =   =   =
  125.      =   = P =   =   =   =   #   =   =   =   =   =
  126.      =   =  \=   =   =   =   #   =   =   =   =   =
  127.      ========\===============#====================
  128.      =   =   =\  =   =   =   #   =   =   =   =   =
  129.      =   =   = \ =   =   =   #   =   =   =   =   =
  130.      =   =   =  \=   =   =   #   =   =   =   =   =
  131.      ============\=======#####====================
  132.      =   =   =   =\  =   #   =   =   =   =   =   =
  133.      =   =   =   = \ =   #   =   =   =   =   =   =
  134.      =   =   =   =  \=   #   =   =   =   =   =   =
  135.      ================\===#========================
  136.      =   =   =   =   =\  #   =   =   =   =   =   =
  137.      =   =   =   =   = \ #   =   =   =   =   =   =
  138.      =   =   =   =   =  \#   =   =   =   =   =   =
  139.      =============================================
  140.  
  141.      (#'s are walls, = is the grid....)
  142.  
  143.      This is just a case of firing a ray for each vertical
  144.   line on the screen. This ray is traced accross the map to
  145.   see where it crosses a grid boundry. Where it crosses a
  146.   boundry you cjeck to see if there is a wall there we see how
  147.   far away it it and draw a scaled vertical line from the texture
  148.   on screen. The line we draw is selected from the texture by
  149.   seeing where the line has intersected on the side of the square it
  150.   hit.
  151.      This is repeated with a ray for each vertical line on the
  152.   screen that we wish to display.
  153.      This is a very quick explaination of how it works missing
  154.   out how the sprites are handled. If you want a more detailed 
  155.   explaination then I suggest getting acksrc.zip from
  156.   ftp.funet.fi in /pub/msdos/games/programming
  157.  
  158.      This is someone's source for a Wolfenstien engine written
  159.   in Borland C and Assembly language on the Pc.
  160.      Its is not the fastest or best but has good documentation
  161.   and solves similiar sprite probelms, distance probelms and has
  162.   some much better explaination of the tracing technique tahn I have
  163.   put here. I recommend to everyone interested taht you get a copy
  164.   and have a thorough play around with it.
  165.   (Even if you don't have a Pc: Everything but the drawing and video
  166.    mode setting is done in 'C' so it should not be too hard to port
  167.    ....)
  168.  
  169.  
  170.   2.2 Ray Casting in the Doom Environment
  171.   =======================================
  172.  
  173.      When you look at a screen from Doom you see floors, steps
  174.   walls and lots of other trappings.
  175.      You look out of windows and accross courtyards and you
  176.   say WOW! what a great 3d game!!
  177.      Then you fire your gun a baddie who's in line with you but
  178.   above you and bang! he's a corpse.
  179.      Then you climb up to the level where the corpse is and look
  180.   out the window to where you were and you say Gosh! a 3d game!!
  181.  
  182.      Hmmm....
  183.  
  184.      Stop gawping at the graphics for a minute and look at the map
  185.   screen. Nice line vectors. But isn't the map a bit simple???
  186.      Notice how depite colours showing you that there are different
  187.   heights. Then notice that despite the fact that there is NEVER a
  188.   place where you can exist on two different levels. Smelling a little
  189.   2d yet???
  190.      Look where there are bridges (or sort of bridges) : managed to
  191.   see under them yet??
  192.  
  193.      The whole point to this is that Doom is a 2D games just like
  194.   its ancestor Wolfenstein but it has rather more advanced raycasting
  195.   which does a very nice job of fooling the player into thinking its a
  196.   3d game that shifting loads of polygons and back-culling, depth
  197.   sorting etc... 
  198.  
  199.      Right the explaination of how you turn a 2d map into the 3d
  200.   doom screen is complex so if you are having difficulty try reading
  201.   it a few times and if all else fails mail me....
  202.  
  203.  
  204.   2.3 What is actually done!
  205.   ==========================
  206.  
  207.      Right to start with the raycasting is started in the same
  208.   way as Wolfenstien. That is find out where the player is in the 2d
  209.   map and get a ray setup for the first vertical line on the screen.
  210.  
  211.      Now we have an extra stage from the Wolfenstein I described
  212.   whcih involves a data srtucture that we will use later to actually
  213.   draw the screen.
  214.  
  215.      In this data structure we start the ray off as at the bottom
  216.   of the screen. This is shown in the diagram below;
  217.  
  218.      =================================
  219.      =                   =
  220.      =                   =
  221.      =                   =
  222.      =                   =
  223.      =                   =
  224.      =                   =
  225.      =                   =
  226.      =                   =
  227.      =                   =
  228.      =                   =
  229.      =                   =
  230.      =                   =
  231.      =                   =
  232.      =                   =
  233.      =                   =
  234.      =                   =
  235.      =*                  =
  236.      =================================
  237.  
  238.  
  239.      Where the '=' show the boundry of the screen and '*' is the virtual
  240.   position of the ray.
  241.  
  242.      Note: the Data structure is really two structures:
  243.      One which is a set of list for each vertical 'scanline' and
  244.      One which is a corresponding list for horizontal scanlines.
  245.  
  246.      Now we start tracing the ray. We skip accross the 2d map until
  247.   we hit something interesting. By something interesting I mean something
  248.   that is an actual wall or florr section edge.
  249.      Right we have hit the edge of either a floor or wall section.
  250.   We have several things to do know. These are;
  251.  
  252.      If it was a wall we hit:
  253.  
  254.   1: Find out how 'high' of screen this section of wall should be
  255.      due to the distance it is accross the 2d map.
  256.   2: Find out at what 'virtual height' it is: This is so that we can see
  257.      where in the vertical scanline in comes for testing where to insert
  258.      it and for clipping it.
  259.   3: Test in our structure to see if you draw it or not.
  260.      (This is done so that you can look through windows : how this works
  261.       will become apparent later.)
  262.   4: If any of the wall segment is visible then we find out where along
  263.      the texture we have hit it and write into the structure the area of
  264.      the screen it takes up as well as the texture, the point where we
  265.      have hit the texture and the size it should be on screen. (This is
  266.      so that we can draw it correctly even if the whole span is not on
  267.      screen.
  268.  
  269.  
  270.      If it was a floor section that we hit:
  271.  
  272.   1: Find out where on the vertical line we are working the floor section
  273.      that the ray has hit is. (We know the height of the the floor in the
  274.      virtual map (2d) and we know the height of the player and the distance
  275.      of the floor square from the player so it is easy).
  276.      As a side effect of this we now know the U,V value where the ray has
  277.      hit the floor square.
  278.  
  279.   2: Trace Accross the floor square till we hit the far edge of the floor
  280.      square : we then workout where this is on the vertical scanline using
  281.      the same technique as above. We now know the vertical span of the
  282.      floor section, and where on the span it is.
  283.  
  284.   3: We check to see if the span is visible on the vertical span.
  285.      If it is or part of it is used then we mark that part of the vertical
  286.      scanline as used.
  287.      We also have to make use of the horizontal buffer I mentioned. We
  288.      insert into this in 2 places. The first is the x coordinate of where
  289.      we hit the floor square into the y line where we where on the screen.
  290.      Phew got that bit?? We also insert here the U,V value which we knew 
  291.      from the tracing. (I told you we'd need it later....)                 
  292.  
  293.  
  294.  
  295.      As you can see there's a little more to hiting a floor segment than
  296. a wall segment. Also note that a you exit a floor segment you may also hit
  297. a wall segment.
  298.  
  299.      Tracing the individual ray is continued until we hit a special kind
  300. of wall. This wall is marked as a wall that connects to the ceiling.
  301. This is one place to stop tracing this ray. However we can stop tracing
  302. early
  303. if we have found enough to fill the whole vertical scanline then we can
  304. stop
  305. whenevr we have done this.
  306.  
  307.      Next come a trick. I said we were tracing along a 2d map. Well I
  308. lied a bit. There are (In my implementation at least..) TWO 2d maps. One is
  309. basically from the floor along including all the 'floor' walls and
  310. everything
  311. up to and including the walls that join onto the ceiling. The other map
  312. is basically the ceiling (with anything coming down from the ceiling on it
  313. if you are doing this: this makes life a little more complex as I'll
  314. explain
  315. below..)
  316.      Now when we have traced along the bottom map and hit a wall that 
  317. connects to the ceiling then we go back and trace along the ceiling from
  318. the start to fill in the gaps. There is a problem with this however.
  319. The problem is when you have things like a monolith or something else built
  320. out of walls jutting down from the ceiling. you have to decide whether to
  321. draw it or draw whatever was already in the scanline structure. This means
  322. either storing extra information in the buffer ie z coordinates or tracing
  323. along both the ceiling and floor at the same time.... for most people I
  324. would
  325. suggest just not having anything jutting down from the ceiling.
  326.      Also you could trace backwards instead of starting a new ray. This 
  327. would be fasterfor many cases as you wouldn't be tracing through lots
  328. of floor squares that aren't on screen. By tracing backwards you can keep
  329. going up the vertical scanline and you know that you are on the screen. As
  330. soon as something goes off the top of the screen you can handle that and
  331. then
  332. stop tracing.
  333.  
  334.      Phew. has everyone got that???
  335.  
  336.      Now we just go back and fire rays up the rest of the vertical
  337. scanlines. Easy!!???
  338.  
  339.      At the end of this lot we have the necessary data in the two buffers
  340. to go back and draw the screen background.
  341. (There is one more thing done while tracing but I'll explain that later...)
  342.  
  343.  
  344.      Oh... one other thing... you have may want to change the raycasting
  345. a bit to subdivide the map... it helps with speed.
  346.      And don't forget the added complexity that walls aren't all at
  347. 90 degrees to each other...
  348.  
  349. 3: Drawing the walls and Why it works!!
  350. =======================================
  351.  
  352.      If you are familiar with Wolfenstein then please still read this
  353. as it is esential background to understanding the floor routine.
  354.  
  355.  
  356.      As all of you probably know the walls are drawn by scaling the line
  357. of the texture to the correct size for the screen. The information in the
  358. vertical buffer makes this easy. What you probably don't know is why this
  359. creates texture mapping that is good enough to fool us.
  360.  
  361.      The wall function is a Affine texture mapping. (well almost)
  362. Now affine texture mappings look abysmal unless you do quite a lot of
  363. subdivision (The amount needed varies according to the angle the projected
  364. square is at.). So why does the Doom technique work??
  365.  
  366.      Well when we traced the rays we found out exactly where along the
  367. side of the square we hit we were in relation to the width of the texture.
  368. This means that the top and bottom pixels of the scaled wall piece are
  369. calculated correctly. This means that we have effecively subdivided the
  370. texture along vertical scanlines and as the effective subdidvisons are
  371. calculated exactly with proper forshortening as a result of the tracing.
  372. So the ray casting has made the texture mapping easy for us.
  373.      (We have enough subdivision by this scanline effect as the wall
  374. only rotates about one axis and we have proper foreshortening.)
  375.  
  376.      This knowlege helps us understand how to do the floors and why
  377. that works.
  378.  
  379.      We can now draw all the wall segments by just looking at the buffer
  380. and drawing the parts marked as walls.(Skiping where we put in the bits
  381. used
  382. by the floor/ceiling bits: we draw them later.)
  383.  
  384. 4:  Drawing the Floor/Ceiling and why it works!
  385. ===============================================
  386.  
  387.      If you have grasped why the walls work then you have just about
  388. won for the floors.
  389.      We have the information needed to draw the floors from the horizontal
  390. buffer.
  391.      All we have to do is look at the horizontal spans in the buffer
  392. and draw them in all.
  393.      Each of these spans has 2 end coordinates for which we have
  394. exact texture coorinates. This tells us which line across the texture
  395. we have to step along to do an Affine or linear mapping.
  396.      This is shown below;
  397.  
  398.  
  399.      =================================
  400.      =                   =
  401.      =                   =
  402.      =                   =
  403.      =                   = U1,V1 (exit)
  404.      =                     **
  405.      =                  ***   =
  406.      =               *** =
  407.      =               ***      =
  408.      =            ***         =
  409.      =         ***       =
  410.      =         ***            =
  411.      =      ***               =
  412.      =    **             =
  413.      =     **            =
  414.      =   **                   =
  415.      = **                =
  416.   U0,V0   **                  =
  417. (entry)   =                   =
  418.      =                   =
  419.      =                   =
  420.      =                   =
  421.      =                   =
  422.      =                   =
  423.      =                   =
  424.      =================================
  425.  
  426. (apologies for the wonky line: it should be straight!!)
  427.  
  428.      Now...as the end coordinates are correct and the axis along
  429. which forshortening takes place is not involved (this is a fudge)
  430. we can step linearly along this line across the texture to approximate
  431. the mapping. (This is far easier than a proper texture map).
  432.      This is effectivly a wall lying on its side which works as the
  433. texture coordinates at the ends of the span have been calculated correctly.
  434. This is a benefit of the raycasting we used to find everything.
  435.      Easy huh??
  436.  
  437.  
  438. 5: Sprites
  439. ==========
  440.  
  441.      The Sprites are really quite easy to do. The basic technique is the
  442. same as used in Wolfenstein 3d.
  443.      This is done as follows:
  444.  
  445. When you enter a 'square' on the floor map you test to see if there are
  446. any sprites in the square. If there are you flag that sprite as visible
  447. and add it to a list of visible sprites.
  448.  
  449. When you have finished tracing and drawing the walls and floor you
  450. depth sort the sprites and draw them from the back to the front. (painters
  451. algorithm). The only complication in drawing them is that you have to check
  452.  
  453. buffer that has the walls in, in order to clip the sprites correctly.
  454.  
  455.      (If you're interested in Doom you can occasionally see large 
  456. explosions (ie BFG) slip partially behind a wall segment.)
  457.  
  458.      On possibly faster way of handling the sprites would be to mark
  459. them like wall segments as you find them in the buffer. The only (ONLY!)
  460. complication to this approach is that sprites can have holes in them. By
  461. this I mean things like the gap between an arm and a leg which should be 
  462. the background colour.
  463.  
  464.  
  465. 6: Lighting and Depth Cueing
  466. ============================
  467.  
  468.      Lighting and Depth Cueing fits nicely in with the way that we have
  469. prepared the screen ready for drawing.
  470.      All we have to do is see how far away we are when we found either
  471. the floor or wall section and set the light level according to the
  472. distance.
  473.      The other thing that is applied is a light level. This is taken from
  474. the map at the edges where you have hit something. As the map is 2D it is
  475. easy to manage lighting, flickering etc.
  476.      For things like pools of light on the floor all you have to do
  477. is subdivide that patch of floor so that you can set the bit under the 
  478. skylight to a lighter colour. Its also very easy to frig this for the
  479. lighting goggles.
  480.  
  481.  
  482. 7: Controlling the Baddies
  483. ==========================
  484.      
  485.  
  486.      This is pretty easy: all you have to think about is moving and
  487. reacting on a 2d map. the only complications are things like the monsters
  488. looking through windows and seeing a player but this all degenerates into
  489. a simple 2d problem. Things like deciding whether the player has been hit
  490. or
  491. has he/she hit a monster is just another case of firing a ray. (Or do it
  492. another way...)
  493.  
  494.  
  495. 8: Where next???
  496. ================
  497.  
  498.      Thats all folks... hopefully a useful and intersting insight into
  499. my Doom engine works.
  500.      As to the question where next... well I already have some enhancements
  501. to my Doom enigine and others are in the works...
  502.  
  503. Some of what you may eventually see are:
  504.  
  505.      Proper lighting (I have done this already...its easier than you
  506.                think)
  507.      Non-Vertical walls (i.e. Aliens style corridors...)
  508.      Orgranic Walls (i.e. Curved like the Aliens nest...)
  509.      Fractal Landscapes (This one is still very much a theory but how
  510.                about being able to go outside and walk up and down
  511.                hills etc??)
  512.  
  513.      If there are bits people are really shaky about I may post a new
  514. version of this... but I cannot get into implimentation issues as all
  515. implementation work is under copyright...
  516.  
  517.      By the way if anyone out there implements this I'd love to here
  518. how you get on...
  519.  
  520.      Anyone got any comments or any other interesting algorithms???
  521. -- 
  522.  
  523. Now lets do Lunar Lander, OK
  524.  
  525. Darryl
  526.  
  527. -- Via DLG Pro v1.0
  528.  
  529.                #####\             _             /#####
  530.                #( )# |          _( )__         | #( )# 
  531.                ##### |         /_    /         | #####
  532.                #" "# |     ___m/I_ //_____     | #" "#
  533.                # O # |____#-x.\ /++m\ /.x-#____| # O #
  534.                #m.m# |   /" \ ///###\\\ / "\   | #m.m#
  535.                #####/    ######/     \######    \#####